/*
 * Copyright 2016 requery.io
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.requery.processor;

import com.squareup.javapoet.AnnotationSpec;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.CodeBlock;
import com.squareup.javapoet.JavaFile;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeName;
import com.squareup.javapoet.TypeSpec;
import io.requery.util.function.Supplier;

import javax.annotation.Generated;
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Modifier;
import javax.lang.model.util.Elements;
import java.io.IOException;

class CodeGeneration {
    private CodeGeneration() {
    }

    static void addGeneratedAnnotation(ProcessingEnvironment processingEnvironment,
                                       TypeSpec.Builder builder) {
        Elements elements = processingEnvironment.getElementUtils();
        if (elements.getTypeElement(Generated.class.getCanonicalName()) != null) {
            builder.addAnnotation(AnnotationSpec.builder(Generated.class)
                .addMember("value", "$S", EntityProcessor.class.getCanonicalName()).build());
        }
    }

    static TypeSpec createAnonymousSupplier(TypeName type, CodeBlock block) {
        return TypeSpec.anonymousClassBuilder("")
            .addSuperinterface(ParameterizedTypeName.get(ClassName.get(Supplier.class), type))
            .addMethod(overridePublicMethod("get")
                .addCode(block)
                .returns(type)
                .build())
            .build();
    }

    static MethodSpec.Builder overridePublicMethod(String name) {
        return MethodSpec.methodBuilder(name)
            .addModifiers(Modifier.PUBLIC)
            .addAnnotation(Override.class);
    }

    static void writeType(ProcessingEnvironment processingEnvironment,
                          String packageName, TypeSpec typeSpec)
        throws IOException {
        JavaFile file = JavaFile.builder(packageName, typeSpec)
            .addFileComment("Generated file do not edit, generated by " +
                EntityProcessor.class.getCanonicalName())
            .indent("    ")
            .build();
        file.writeTo(processingEnvironment.getFiler());
    }
}
